﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Linq.Expressions;
using System.Text.RegularExpressions;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Windows.Media.Imaging;
using ImageTools;
using ImageTools.IO.Png;
using ImageTools.IO.Jpeg;
using ImageTools.IO.Gif;
using ImageTools.IO.Bmp;

namespace AuroraPlatform.Tools
{
    public static class Utility
    {
        public static byte[] ReadFully(Stream stream, int initialLength = 32768)
        {
            // If we've been passed an unhelpful initial length, just
            // use 32K.
            if (initialLength < 1)
            {
                initialLength = 32768;
            }

            byte[] buffer = new byte[initialLength];
            int read = 0;

            int chunk;
            stream.Position = 0;
            while ((chunk = stream.Read(buffer, read, buffer.Length - read)) > 0)
            {
                read += chunk;

                // If we've reached the end of our buffer, check to see if there's
                // any more information
                if (read == buffer.Length)
                {
                    int nextByte = stream.ReadByte();

                    // End of stream? If so, we're done
                    if (nextByte == -1)
                    {
                        return buffer;
                    }

                    // Nope. Resize the buffer, put in the byte we've just
                    // read, and continue
                    byte[] newBuffer = new byte[buffer.Length * 2];
                    Array.Copy(buffer, newBuffer, buffer.Length);
                    newBuffer[read] = (byte)nextByte;
                    buffer = newBuffer;
                    read++;
                }
            }
            // Buffer is now too big. Shrink it.
            byte[] ret = new byte[read];
            Array.Copy(buffer, ret, read);
            return ret;
        }

        public static byte[] ConvertFromJPG(Stream stream)
        {
            ExtendedImage decoderImage = null;
            using (stream)
            {
                JpegDecoder decoder = new JpegDecoder();
                decoderImage = new ExtendedImage();
                decoder.Decode(decoderImage, stream);
            }

            byte[] bytes = null;
            PngEncoder encoder = null;
            using (MemoryStream ms = new MemoryStream())
            {
                encoder = new PngEncoder();
                encoder.Encode(decoderImage, ms);
                bytes = ms.ToArray();
            }

            return bytes;
        }

        public static byte[] ConvertFromBMP(Stream stream)
        {
            ExtendedImage decoderImage = null;
            using (stream)
            {
                BmpDecoder decoder = new BmpDecoder();
                decoderImage = new ExtendedImage();
                decoder.Decode(decoderImage, stream);
            }

            byte[] bytes = null;

            JpegEncoder encoder = null;
            using (MemoryStream ms = new MemoryStream())
            {
                encoder = new JpegEncoder();
                encoder.Encode(decoderImage, ms);
                bytes = ms.ToArray();
            }

            return bytes;
        }


        public static ImageSource ConvertFromJPG(byte[] bytes)
        {
            ExtendedImage decoderImage = null;
            using(MemoryStream ms = new MemoryStream(bytes))
            {
                JpegDecoder decoder = new JpegDecoder();
                decoderImage = new ExtendedImage();
                decoder.Decode(decoderImage, ms);
            }

            BitmapImage bitmapImage= null;
            PngEncoder encoder = null;
            using(MemoryStream ms = new MemoryStream())
            {
                encoder = new PngEncoder();
                encoder.Encode(decoderImage, ms);
                bitmapImage = new BitmapImage();
                bitmapImage.SetSource(ms);
            }

            return bitmapImage;
        }

        public static ImageSource ConvertFromGIF(byte[] bytes)
        {
            ExtendedImage decoderImage = null;
            using (MemoryStream ms = new MemoryStream(bytes))
            {
                GifDecoder decoder = new GifDecoder();
                decoderImage = new ExtendedImage();
                decoder.Decode(decoderImage, ms);
            }

            BitmapImage bitmapImage = null;
            PngEncoder encoder = null;
            using (MemoryStream ms = new MemoryStream())
            {
                encoder = new PngEncoder();
                encoder.Encode(decoderImage, ms);
                bitmapImage = new BitmapImage();
                bitmapImage.SetSource(ms);
            }

            return bitmapImage;
        }

        public static byte[] GetBytes(BitmapImage bi)
        {
            WriteableBitmap wbm = new WriteableBitmap(bi);
            return wbm.ToByteArray();
        }

        public static byte[] ToByteArray(this WriteableBitmap bmp)
        {
            // Init buffer
            int w = bmp.PixelWidth;
            int h = bmp.PixelHeight;
            int[] p = bmp.Pixels;
            int len = p.Length;
            byte[] result = new byte[4 * w * h];

            // Copy pixels to buffer
            for (int i = 0, j = 0; i < len; i++, j += 4)
            {
                int color = p[i];
                result[j + 0] = (byte)(color >> 24); // A
                result[j + 1] = (byte)(color >> 16); // R
                result[j + 2] = (byte)(color >> 8);  // G
                result[j + 3] = (byte)(color);       // B
            }

            return result;
        }

        public static ImageSource ConverteToImage(byte[] bytes)
        {
            BitmapImage bi = null;
            using (MemoryStream ms = new MemoryStream(bytes, 0, bytes.Length))
            {
                bi = new BitmapImage();
                bi.SetSource(ms);
            }
            return bi;
        }

        public static long DateTimeToLong(this DateTime d)
        {
            return (long)(d.AddHours(-8) - new DateTime(1970, 1, 1)).TotalSeconds;

        }
        public static DateTime DateTimeFromLong(this long d)
        {
            return new DateTime(1970, 1, 1).AddHours(8).AddSeconds(d);
        }


        //public static string SerializeToJsonString(object objectToSerialize)
        //{
        //    using (MemoryStream ms = new MemoryStream())
        //    {
        //        DataContractJsonSerializer serializer =
        //                new DataContractJsonSerializer(objectToSerialize.GetType());
        //        serializer.WriteObject(ms, objectToSerialize);
        //        ms.Position = 0;

        //        using (StreamReader reader = new StreamReader(ms))
        //        {
        //            return reader.ReadToEnd();
        //        }
        //    }
        //}

        //public static T Deserialize<T>(string jsonString)
        //{
        //    using (MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(jsonString)))
        //    {
        //        DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(T));

        //        return (T)serializer.ReadObject(ms);
        //    }
        //}
    }
}
